///////////////////////////////////////////////////
/// tototoy Code
/// $Id: traceback.cc 39 2009-10-26 06:15:00Z tonyjobmails $
/// $Date: 2009-10-26 06:15:00 +0000 (Mon, 26 Oct 2009) $
/// $Author: tonyjobmails $
/// $Revision: 39 $
/// E-mail: tonyjobmails@gmail.com
/// filename: traceback.cc
/// function: 程序中输出bt信息, 动态跟踪函数调试
///////////////////////////////////////////////////

#include <iostream>
#include <stdlib.h>
#include <cxxabi.h>
#include "traceback.h"

namespace tototoy
{
	///////////////////////////////////////////////
	/// @brief 程序中输出bt信息，动态跟踪函数调试
	void print_trace_symbols(void)
	{
		/// 堆栈的最大深度
		const int MAX_DEPTH = 32;

		void *traceback[MAX_DEPTH + 1];
		size_t size = 0;
		char **btstrings;
		size_t pos = 0;

		size = backtrace(traceback, MAX_DEPTH);

		if(size == 0)
		{
#ifdef _TONY_DEBUG
			std::cout << "backtrace return a inefficient value of 0" << std::endl;
#endif
			return;
		}

		btstrings = backtrace_symbols(traceback, size);

		size_t funcname_size = 256;
		char* funcname = (char *)malloc(funcname_size * sizeof(char));

		if(funcname && btstrings)
		{
			for(pos = 0; pos < size; ++pos)
			{
				char *begin_name = NULL;
				char *begin_offset = NULL;
				char *end_offset = NULL;

				for(char *p = btstrings[pos]; *p; ++p)
				{
					if(*p == '(')
					{
						begin_name = p;
					}
					else if(*p == '+')
					{
						begin_offset = p;
					}
					else if(*p == ')' && begin_offset)
					{
						end_offset = p;
						break;
					}
				}

				if(begin_name && begin_offset && end_offset && begin_name < begin_offset)
				{
					*begin_name++ = 0;
					*begin_offset++ = 0;
					*end_offset++ = 0;

					int status = 0;
					char *ret = abi::__cxa_demangle(begin_name, funcname, &funcname_size, &status);
					if(status == 0)
					{
						if(ret)
						{
							funcname = ret;
							std::cout << "[backtrace_]#" << pos << " " << btstrings[pos] << ": "
							     <<  funcname << "(...)+" << begin_offset << std::endl;
						}
					}
					else
					{
						std::cout << "[backtrace_]#" << pos << " " << btstrings[pos] << ": " << begin_name
						          << "(...)+" << begin_offset << std::endl;
					}
				}
				else
				{
					std::cout << "[backtrace]#" << pos << " " << btstrings[pos] << std::endl;
				}
			}

			free(btstrings);
			free(funcname);
		}
	}
	///////////////////////////////////////////////
};

